package testcases;

import static org.junit.Assert.*;

import java.io.ByteArrayOutputStream;
import java.io.PrintStream;

import org.junit.Before;
import org.junit.Test;

import code.CheckingAccount;
import code.CreditCard;
import code.DebitCard;
import code.SavingsAccount;

public class CheckingAccountTest {
	CheckingAccount normal_account = new CheckingAccount("Billy", "1 main st.", "12345","Seattle", "USA");
	CheckingAccount account_debt =  new CheckingAccount("Joe", "3rd C st.", "67890", "Tacoma", "USA", -3.6f);
	CheckingAccount own_account_num = new CheckingAccount(123);

	public void runTest(){
		normalAccountConstructor();
		debtAccountConstructor();
		ownAccountNumConstructor();
		testDetermineCost();
		testPrint();
		testWithdrawal();
		testVerseMoney();
		testApplyForCreditCard();
		testGetDebt();
		testGetAccountNum();
		testEquals();
	}

	public void normalAccountConstructor() {
		assertEquals(0, normal_account.fAccountNumber);//why 1?
		assertEquals("Billy", normal_account.fName);
		assertEquals("1 main st.", normal_account.fStreet);
		assertEquals("12345", normal_account.fZipcode);
		assertEquals("Seattle", normal_account.fTown);
		assertEquals("USA", normal_account.fCountry);
		assertFalse(normal_account.fDebitAllowed);
		assertEquals(0.0, normal_account.fDebitAmount, 0.0);	
	}
	
	public void debtAccountConstructor() {
		assertEquals(1, account_debt.fAccountNumber);
		assertEquals("Joe", account_debt.fName);
		assertEquals("3rd C st.", account_debt.fStreet);
		assertEquals("67890", account_debt.fZipcode);
		assertEquals("Tacoma", account_debt.fTown);
		assertEquals("USA", account_debt.fCountry);
		assertTrue(account_debt.fDebitAllowed);
		assertEquals(-3.6f, account_debt.fDebitAmount, -3.6f);	
	}

	public void ownAccountNumConstructor(){
		assertEquals(123,own_account_num.fAccountNumber);
	}

	public void testDetermineCost(){
		normal_account.determineCosts();
		account_debt.determineCosts();
		own_account_num.determineCosts();
		
		
		assertEquals(-0.953, normal_account.getBalance(), -0.953);
		assertEquals(-0.953, account_debt.getBalance(), -0.953);
		assertEquals(-0.953, own_account_num.getBalance(), -0.953);
		
		normal_account.fBalance = 100.0;
		account_debt.fBalance = 100.0;
		own_account_num.fBalance = 100.0;
		
		normal_account.determineCosts();
		account_debt.determineCosts();
		own_account_num.determineCosts();
		
		assertEquals(99.0, normal_account.getBalance(), 99.0);
		assertEquals(99.0, account_debt.getBalance(), 99.0);
		assertEquals(99.0, own_account_num.getBalance(), 99.0);

		
		//resets the balance for testing purposes. 
		normal_account.setBalance(0.0);
		account_debt.setBalance(0.0);
		own_account_num.setBalance(0.0);
	}
	
	public void testPrint(){
		ByteArrayOutputStream outContent = new ByteArrayOutputStream();
		System.setOut(new PrintStream(outContent));

		String normal_account_string = "**************************************\n"
				+ "Savings account:     0\n"
				+ "Account holder name: Billy\n"
				+ "Address:             1 main st.\n"
				+ "                     12345 Seattle\n"
				+ "USA\n"
				+ "**************************************\n"
				+ "Balance:  0.0\n"
				+ "**************************************\n";
		
		String account_debt_string = "**************************************\n"
				+ "Savings account:     1\n"
				+ "Account holder name: Joe\n"
				+ "Address:             3rd C st.\n"
				+ "                     67890 Tacoma\n"
				+ "USA\n"
				+ "**************************************\n"
				+ "Balance:  0.0\n"
				+ "**************************************\n";
		
		normal_account.print();
		assertEquals(normal_account_string, outContent.toString());

		System.setOut(null);
		outContent = new ByteArrayOutputStream();
		System.setOut(new PrintStream(outContent));
		
		account_debt.print();
		assertEquals(account_debt_string, outContent.toString());
	}
	
	public void testWithdrawal(){
		//account balance = 0
		assertFalse(normal_account.withdrawal(1.0));
		normal_account.fBalance = 100.00;
		assertFalse(normal_account.withdrawal(1.0));
		assertTrue(account_debt.withdrawal(1.00));
	
		normal_account.fBalance = 0.0;
	}
	
	public void testVerseMoney(){
		normal_account.verseMoney(100.00);
		account_debt.verseMoney(100.00);
		own_account_num.verseMoney(100.00);
		
		assertEquals(99.047, normal_account.getBalance(), 100.00);
		assertEquals(99.047, account_debt.getBalance(), 100.00);
		assertEquals(99.047, own_account_num.getBalance(), 100.00);
		
		normal_account.verseMoney(-200.00);
		account_debt.verseMoney(-200.00);
		own_account_num.verseMoney(-200.00);

		assertEquals(-100.0, normal_account.getBalance(), 1.00);
		assertEquals(-100.0, account_debt.getBalance(), 1.00);
		assertEquals(-100.0, own_account_num.getBalance(), 1.00);
		
		//resets the balance for testing purposes. 
		normal_account.setBalance(0.0);
		account_debt.setBalance(0.0);
		own_account_num.setBalance(0.0);
	}
	
	public void testApplyForCreditCard(){
		//all fBalances = 0
		assertTrue(normal_account.applyForCreditCard("Billy", "1 main st.", "12345","Seattle", "USA", 0));
		assertTrue(normal_account.applyForCreditCard("Joe", "3rd C st.", "67890", "Tacoma", "USA", 1));
		assertTrue(normal_account.applyForCreditCard("Bob", "1 main st.", "12345","Seattle", "USA", 123));
		
		//all fBalances = -100
		normal_account.decreaseBalance(100.00);
		account_debt.decreaseBalance(100.00);
		own_account_num.decreaseBalance(100.00);
		
		assertFalse(normal_account.applyForCreditCard("Billy", "1 main st.", "12345","Seattle", "USA", 0));
		assertFalse(normal_account.applyForCreditCard("Joe", "3rd C st.", "67890", "Tacoma", "USA", 1));
		assertFalse(normal_account.applyForCreditCard("Bob", "1 main st.", "12345","Seattle", "USA", 123));
		
		//all fBalances equal 2501
		normal_account.increaseBalance(2601.00);
		account_debt.increaseBalance(2601.00);
		own_account_num.increaseBalance(2601.00);
		
		assertTrue(normal_account.applyForCreditCard("Billy", "1 main st.", "12345","Seattle", "USA", 0));
		assertTrue(normal_account.applyForCreditCard("Joe", "3rd C st.", "67890", "Tacoma", "USA", 1));
		assertTrue(normal_account.applyForCreditCard("Bob", "1 main st.", "12345","Seattle", "USA", 123));
		
		//resets the balance for testing purposes. 
		normal_account.setBalance(0.0);
		account_debt.setBalance(0.0);
		own_account_num.setBalance(0.0);
	}
	
	public void testGetDebt(){
		assertEquals(-3.6f, account_debt.getDebitAmount(), -3.6f);
		assertEquals(0.0, normal_account.getDebitAmount(), 0.0);
		assertEquals(0.0, own_account_num.getDebitAmount(), 0.0);
	}
	
	public void testGetAccountNum(){
		assertEquals(0, normal_account.getAccountNumber());
		assertEquals(1, account_debt.getAccountNumber());
		assertEquals(123, own_account_num.getAccountNumber());
	}
	
	public void testEquals(){
		assertTrue(normal_account.equals(normal_account));
		assertTrue(account_debt.equals(account_debt));
		assertTrue(own_account_num.equals(own_account_num));
		
		assertFalse(normal_account.equals(account_debt));
		assertFalse(account_debt.equals(normal_account));
		assertFalse(own_account_num.equals(account_debt));
	}
	
	
}
